package rediscli

import (
	"context"
	"fmt"
	"time"

	"github.com/bsm/redislock"
	"github.com/go-redis/redis/v8"
	"github.com/gogf/gf/frame/g"
	bloom "github.com/zhwei820/gobloom"
)

var Rdb *redis.Client
var Locker *redislock.Client

func init() {

	opt, err := redis.ParseURL(g.Config().GetString("REDIS_URL"))
	if err != nil {
		panic(err)
	}

	Rdb = redis.NewClient(opt)
	Locker = redislock.New(Rdb)

}

func Lock(key string, fn func() error) error {
	ctx := context.Background()
	// Try to obtain lock.
	option := &redislock.Options{RetryStrategy: redislock.ExponentialBackoff(50*time.Millisecond, 10000*time.Millisecond)}
	lock, err := Locker.Obtain(ctx, key, 30*time.Second, option)
	if err == redislock.ErrNotObtained {
		g.Log().Info("Could not obtain lock! key: ", key)
		return err

	} else if err != nil {
		g.Log().Error(err)
		return err
	}
	t1 := time.Now()

	// Don't forget to defer Release.
	defer func() {
		if lock != nil {
			t2 := time.Now()
			g.Log().Info("Lock Release key! :", key, t2.Sub(t1).Nanoseconds()/1e9)
			lock.Release(ctx)
		}
	}()
	if err := fn(); err != nil {
		g.Log().Info("fn_error! key! :", key, err)
	} else {
		g.Log().Info("fn_ok! key! :", key, err)
	}
	return nil
}

var NN = uint(10000000)

func BloomAdd(key, val string) {
	filter := bloom.New(Rdb, key, NN)
	filter.Add([]byte(val))
}

func BloomExists(key, val string) (ok bool, err error) {
	filter := bloom.New(Rdb, key, NN)
	ok, err = filter.Exists([]byte(val))
	return
}

func demo() {
	res := Rdb.Ping(context.Background())
	g.Log().Info("res", res)

	ret := Rdb.Get(context.Background(), "obj.BatchId")
	fmt.Println("ret", g.Export(ret.Err()))
	Rdb.Set(context.Background(), "obj.BatchId", 1, 1*time.Second)
	ret = Rdb.Get(context.Background(), "obj.BatchId")
	fmt.Println("ret", g.Export(ret.Err()))

	BloomAdd("test_key", "64")
	ok, err := BloomExists("test_key", "64")
	fmt.Println("ok, err", ok, err)
	ok, err = BloomExists("test_key", "642")
	fmt.Println("ok, err", ok, err)

}
